﻿using Common.Communication;
using Common.Tool.DataTools;
using DeviceBase.Enums;
using DeviceBase.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading.Tasks;

namespace DianZiFuZai.Core.Itech
{
    public class IT8511SerialPort : SerialPortBase,IDianZiFuZai
    {
        public string Name { get ; set; }
        byte Addr;
        public IT8511SerialPort(string name, int addr, string portName, int baudRate = 115200, int timeout = 1000) : base(portName, baudRate, timeout: timeout)
        {
            Name = name;
            Addr = (byte)addr;
        }


        public Result<double> ReadCurrentValue(DianZiFuZaiEnum.FuZaiMode mode)
        {
            Result<double> result = new Result<double>();
            AppendInfo(Name, $"读取当前负载值");
            var command = CmdSetControlMode(true);
            var re = WriteThenRead(command);
            var want = CmdSetOk;
            if (!re.IsSucceed || !re.Value.Take(want.Length).SequenceEqual(want))
            {
                result.IsSucceed = false;
                result.Err = "设置远端通信失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            command = CmdReadCurrentValue();
            re = WriteThenRead(command);
            want = CmdReadCurrentValueOk;
            if (!re.IsSucceed || !re.Value.Take(want.Length).SequenceEqual(want))
            {
                result.IsSucceed = false;
                result.Err = "读取当前负载值失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            if (mode == DianZiFuZaiEnum.FuZaiMode.电压)
            {
                result.Value = ((re.Value[6] << 24) + (re.Value[5] << 16) + (re.Value[4] << 8) + re.Value[3]) / 1000.0f;
                AppendResult(Name, DataConvert.ToUnit(result.Value, "F3") + "V");
            }
            if (mode == DianZiFuZaiEnum.FuZaiMode.电流)
            {
                result.Value = ((re.Value[10] << 24) + (re.Value[9] << 16) + (re.Value[8] << 8) + re.Value[7]) / 10000.0f;
                AppendResult(Name, DataConvert.ToUnit(result.Value, "F3") + "A");
            }
            if (mode == DianZiFuZaiEnum.FuZaiMode.功率)
            {
                result.Value = ((re.Value[14] << 24) + (re.Value[13] << 16) + (re.Value[12] << 8) + re.Value[11]) / 1000.0f;
                AppendResult(Name, DataConvert.ToUnit(result.Value, "F3") + "W");
            }
            return result.EndTime();
        }

        public Result<double> ReadSetValue(DianZiFuZaiEnum.FuZaiMode mode)
        {
            Result<double> result = new Result<double>();
            AppendInfo(Name, $"读取设置负载值");
            var command = CmdSetControlMode(true);
            var re = WriteThenRead(command);
            var want = CmdSetOk;
            if (!re.IsSucceed || !re.Value.Take(want.Length).SequenceEqual(want))
            {
                result.IsSucceed = false;
                result.Err = "设置远端通信失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            command = CmdReadFuZaiValue(mode);
            re = WriteThenRead(command);
            want = CmdReadFuZaiValueOk(mode);
            if (!re.IsSucceed || !re.Value.Take(want.Length).SequenceEqual(want))
            {
                result.IsSucceed = false;
                result.Err = "读取设置负载值失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            result.Value = ((re.Value[6] << 24) + (re.Value[5] << 16) + (re.Value[4] << 8) + re.Value[3]);
            if (mode == DianZiFuZaiEnum.FuZaiMode.电压)
            {
                result.Value = result.Value / 1000.0f;
                AppendResult(Name, DataConvert.ToUnit(result.Value, "F3") + "V");
            }
            if (mode == DianZiFuZaiEnum.FuZaiMode.电流)
            {
                result.Value = result.Value / 10000.0f;
                AppendResult(Name, DataConvert.ToUnit(result.Value, "F3") + "A");
            }
            if (mode == DianZiFuZaiEnum.FuZaiMode.功率)
            {
                result.Value = result.Value / 1000.0f;
                AppendResult(Name, DataConvert.ToUnit(result.Value, "F3") + "W");
            }
            if (mode == DianZiFuZaiEnum.FuZaiMode.电阻)
            {
                result.Value = result.Value / 1000.0f;
                AppendResult(Name, DataConvert.ToUnit(result.Value, "F3") + "Ω");
            }
            return result.EndTime();
        }

        public Result<bool> SetFuZai(DianZiFuZaiEnum.FuZaiMode mode, double value)
        {
            Result<bool> result = new Result<bool>();
            AppendInfo(Name, $"设置负载定值{value}");
            var command = CmdSetControlMode(true);
            var re = WriteThenRead(command);
            var want = CmdSetOk;
            if (!re.IsSucceed || !re.Value.Take(want.Length).SequenceEqual(want))
            {
                result.IsSucceed = false;
                result.Err = "设置远端通信失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            command = CmdSetFuZaiValue(mode, value);
            re = WriteThenRead(command);
            if (!re.IsSucceed || !re.Value.Take(CmdSetOk.Length).SequenceEqual(CmdSetOk))
            {
                result.IsSucceed = false;
                result.Err = "设置负载定值失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            command = CmdReadFuZaiValue(mode);
            re = WriteThenRead(command);
            want = CmdReadFuZaiValueOk(mode);
            if (!re.IsSucceed || !re.Value.Take(want.Length).SequenceEqual(want))
            {
                result.IsSucceed = false;
                result.Err = "读取设置负载定值失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            double set  = ((re.Value[6] << 24) + (re.Value[5] << 16) + (re.Value[4] << 8) + re.Value[3]);
            if (mode == DianZiFuZaiEnum.FuZaiMode.电压)
            {
                set = set / 1000.0f;
                AppendResult(Name, DataConvert.ToUnit(result.Value, "F3") + "V");
            }
            if (mode == DianZiFuZaiEnum.FuZaiMode.电流)
            {
                set = set / 10000.0f;
                AppendResult(Name, DataConvert.ToUnit(result.Value, "F3") + "A");
            }
            if (mode == DianZiFuZaiEnum.FuZaiMode.功率)
            {
                set = set / 1000.0f;
                AppendResult(Name, DataConvert.ToUnit(result.Value, "F3") + "W");
            }
            if (mode == DianZiFuZaiEnum.FuZaiMode.电阻)
            {
                set = set  / 1000.0f;
                AppendResult(Name, DataConvert.ToUnit(result.Value, "F3") + "Ω");
            }
            if (set != value)
            {
                result.IsSucceed = false;
                result.Err = "设置负载定值失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            return result.EndTime();
        }

        public Result<bool> SetFuZaiMode(DianZiFuZaiEnum.FuZaiMode mode)
        {
            Result<bool> result = new Result<bool>();
            AppendInfo(Name, $"设置负载模式{mode.ToString()}");
            var command = CmdSetControlMode(true);
            var re = WriteThenRead(command);
            var want = CmdSetOk;
            if (!re.IsSucceed || !re.Value.Take(want.Length).SequenceEqual(want))
            {
                result.IsSucceed = false;
                result.Err = "设置远端通信失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            command = CmdSetFuZaiMode(mode);
            re = WriteThenRead(command);
            if (!re.IsSucceed || !re.Value.Take(CmdSetOk.Length).SequenceEqual(CmdSetOk))
            {
                result.IsSucceed = false;
                result.Err = "设置负载模式失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            command = CmdReadFuZaiMode();
            re = WriteThenRead(command);
            want = CmdReadFuZaiModeOk(mode);
            if (!re.IsSucceed || !re.Value.Take(want.Length).SequenceEqual(want))
            {
                result.IsSucceed = false;
                result.Err = "读取设置负载模式失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            return result.EndTime();
        }

        public Result<bool> SetMaxFuZai(DianZiFuZaiEnum.FuZaiMode mode,double maxInput)
        {
            Result<bool> result = new Result<bool>();
            AppendInfo(Name, $"设置最大负载{maxInput}");
            var command = CmdSetControlMode(true);
            var re = WriteThenRead(command);
            var want = CmdSetOk;
            if (!re.IsSucceed || !re.Value.Take(want.Length).SequenceEqual(want))
            {
                result.IsSucceed = false;
                result.Err = "设置远端通信失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            command = CmdSetMaxInput(mode,maxInput);
            re = WriteThenRead(command);
            if (!re.IsSucceed || !re.Value.Take(CmdSetOk.Length).SequenceEqual(CmdSetOk))
            {
                result.IsSucceed = false;
                result.Err = "设置负载模式失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            command = CmdReadMaxInput(mode);
            re = WriteThenRead(command);
            want = CmdReadMaxInputOk(mode, maxInput);
            if (!re.IsSucceed || !re.Value.Take(want.Length).SequenceEqual(want))
            {
                result.IsSucceed = false;
                result.Err = "读取设置负载模式失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            return result.EndTime();
        }

        public Result<bool> SetStatus(bool enable)
        {
            Result<bool> result = new Result<bool>();
            AppendInfo(Name, $"设置负载状态{enable}");
            var command = CmdSetControlMode(true);
            var re = WriteThenRead(command);
            var want = CmdSetOk;
            if (!re.IsSucceed || !re.Value.Take(want.Length).SequenceEqual(want))
            {
                result.IsSucceed = false;
                result.Err = "设置远端通信失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            command = CmdSetStatus(enable);
            re = WriteThenRead(command);
            if (!re.IsSucceed || !re.Value.Take(CmdSetOk.Length).SequenceEqual(CmdSetOk))
            {
                result.IsSucceed = false;
                result.Err = "设置负载状态失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            return result.EndTime();
        }

        public double VolMin = 0;
        public double VolMax = 120.000f;
        public double CurMin = 0;
        public double CurMax = 20.0000f;
        public double WattMin = 0;
        public double WattMax = 120.000f;
        public double RMin = 0;
        public double RMax = 4000.000f;

        byte[] CmdSetControlMode(bool remote)
        {
            byte remoteByte = Convert.ToByte(remote == true ? 0x01 : 0x00);
            byte[] order = new byte[25] { 0xAA, Addr, 0x20, remoteByte,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00 , 0x00 };
            return ByteHelper.GetSumCcBytes(order);
        }
        byte[] CmdSetStatus(bool enable)
        {
            byte enableByte = Convert.ToByte(enable == true ? 0x01 : 0x00);
            byte[] order = new byte[25] { 0xAA, Addr, 0x21, enableByte,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00 , 0x00 };
            return ByteHelper.GetSumCcBytes(order);
        }
        byte[] CmdSetOk => new byte[4] { 0xAA, Addr, 0x12, 0x80 };
        
        byte[] CmdSetMaxInput(DianZiFuZaiEnum.FuZaiMode mode, double value)
        {
            byte modeByte = 0x22;
            int maxValue = 0;
            switch (mode)
            {
                case DianZiFuZaiEnum.FuZaiMode.电压: modeByte = 0x22; maxValue = Convert.ToInt32(value * 1000); break;
                case DianZiFuZaiEnum.FuZaiMode.电流: modeByte = 0x24; maxValue = Convert.ToInt32(value * 10000); break;
                case DianZiFuZaiEnum.FuZaiMode.功率: modeByte = 0x26; maxValue = Convert.ToInt32(value * 1000); break;
                default:
                    break;
            }
            byte low1 = Convert.ToByte(maxValue & 0xff);
            byte low2 = Convert.ToByte((maxValue >> 8) & 0xff);
            byte high1 = Convert.ToByte((maxValue >> 16) & 0xff);
            byte high2 = Convert.ToByte((maxValue >> 24) & 0xff);
            byte[] order = new byte[25] { 0xAA, Addr, modeByte,low1,low2,high1,high2,
               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00 , 0x00 };
            return ByteHelper.GetSumCcBytes(order);
        }
        byte[] CmdReadMaxInput(DianZiFuZaiEnum.FuZaiMode mode)
        {
            byte modeByte = 0x23;
            switch (mode)
            {
                case DianZiFuZaiEnum.FuZaiMode.电压: modeByte = 0x23; break;
                case DianZiFuZaiEnum.FuZaiMode.电流: modeByte = 0x25; break;
                case DianZiFuZaiEnum.FuZaiMode.功率: modeByte = 0x27; break;
                default:
                    break;
            }
            byte[] order = new byte[25] { 0xAA, Addr, modeByte,0x00, 0x00, 0x00, 0x00,
               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00 , 0x00 };
            return ByteHelper.GetSumCcBytes(order);
        }
        byte[] CmdReadMaxInputOk(DianZiFuZaiEnum.FuZaiMode mode, double value)
        {
            byte modeByte = 0x23;
            int maxValue = 0;
            switch (mode)
            {
                case DianZiFuZaiEnum.FuZaiMode.电压: modeByte = 0x23; maxValue = Convert.ToInt32(value * 1000); break;
                case DianZiFuZaiEnum.FuZaiMode.电流: modeByte = 0x25; maxValue = Convert.ToInt32(value * 10000); break;
                case DianZiFuZaiEnum.FuZaiMode.功率: modeByte = 0x27; maxValue = Convert.ToInt32(value * 1000); break;
                default:
                    break;
            }
            byte low1 = Convert.ToByte(maxValue & 0xff);
            byte low2 = Convert.ToByte((maxValue >> 8) & 0xff);
            byte high1 = Convert.ToByte((maxValue >> 16) & 0xff);
            byte high2 = Convert.ToByte((maxValue >> 24) & 0xff);
            byte[] order = new byte[7] { 0xAA, Addr, modeByte, low1, low2, high1, high2 };
            return order;
        }
        byte[] CmdSetFuZaiValue(DianZiFuZaiEnum.FuZaiMode mode, double value)
        {
            byte modeByte = 0x2A;
            int setValue = 0;
            switch (mode)
            {
                case DianZiFuZaiEnum.FuZaiMode.电压: modeByte = 0x2C; setValue = Convert.ToInt32(value * 1000); break;
                case DianZiFuZaiEnum.FuZaiMode.电流: modeByte = 0x2A; setValue = Convert.ToInt32(value * 10000); break;
                case DianZiFuZaiEnum.FuZaiMode.功率: modeByte = 0x2E; setValue = Convert.ToInt32(value * 1000); break;
                case DianZiFuZaiEnum.FuZaiMode.电阻: modeByte = 0x30; setValue = Convert.ToInt32(value * 1000); break;
                default:
                    break;
            }
            byte low1 = Convert.ToByte(setValue & 0xff);
            byte low2 = Convert.ToByte((setValue >> 8) & 0xff);
            byte high1 = Convert.ToByte((setValue >> 16) & 0xff);
            byte high2 = Convert.ToByte((setValue >> 24) & 0xff);
            byte[] order = new byte[25] { 0xAA, Addr, modeByte,low1,low2,high1,high2,
               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00 , 0x00 };
            return ByteHelper.GetSumCcBytes(order);
        }
        byte[] CmdReadFuZaiValue(DianZiFuZaiEnum.FuZaiMode mode)
        {
            byte modeByte = 0x2B;
            switch (mode)
            {
                case DianZiFuZaiEnum.FuZaiMode.电压: modeByte = 0x2D; break;
                case DianZiFuZaiEnum.FuZaiMode.电流: modeByte = 0x2B; break;
                case DianZiFuZaiEnum.FuZaiMode.功率: modeByte = 0x2F; break;
                case DianZiFuZaiEnum.FuZaiMode.电阻: modeByte = 0x31; break;
                default:
                    break;
            }
            byte[] order = new byte[25] { 0xAA, Addr, modeByte,0x00, 0x00, 0x00, 0x00,
               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00 , 0x00 };
            return ByteHelper.GetSumCcBytes(order);
        }
        byte[] CmdReadFuZaiValueOk(DianZiFuZaiEnum.FuZaiMode mode)
        {
            byte modeByte = 0x2B;
            switch (mode)
            {
                case DianZiFuZaiEnum.FuZaiMode.电压: modeByte = 0x2D;  break;
                case DianZiFuZaiEnum.FuZaiMode.电流: modeByte = 0x2B;  break;
                case DianZiFuZaiEnum.FuZaiMode.功率: modeByte = 0x2F;  break;
                case DianZiFuZaiEnum.FuZaiMode.电阻: modeByte = 0x31;  break;
                default:
                    break;
            }
            byte[] order = new byte[3] { 0xAA, Addr, modeByte};
            return order;
        }
        byte[] CmdSetFuZaiMode(DianZiFuZaiEnum.FuZaiMode mode)
        {
            byte modeByte = 0x28;
            byte type = 0x01;
            switch (mode)
            {
                case DianZiFuZaiEnum.FuZaiMode.电压: type = 0x01; break;
                case DianZiFuZaiEnum.FuZaiMode.电流: type = 0x00; break;
                case DianZiFuZaiEnum.FuZaiMode.功率: type = 0x02; break;
                case DianZiFuZaiEnum.FuZaiMode.电阻: type = 0x03; break;
                default:
                    break;
            }
            byte[] order = new byte[25] { 0xAA, Addr, modeByte,type,0x00, 0x00, 0x00,
               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00 , 0x00 };
            return ByteHelper.GetSumCcBytes(order);
        }
        byte[] CmdReadFuZaiMode()
        {
            byte typeByte = 0x29;
            byte[] order = new byte[25] { 0xAA, Addr, typeByte,0x00, 0x00, 0x00, 0x00,
               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00 , 0x00 };
            return ByteHelper.GetSumCcBytes(order);
        }
        byte[] CmdReadFuZaiModeOk(DianZiFuZaiEnum.FuZaiMode mode)
        {
            byte modeByte = 0x29;
            byte type = 0x01;
            switch (mode)
            {
                case DianZiFuZaiEnum.FuZaiMode.电压: type = 0x01; break;
                case DianZiFuZaiEnum.FuZaiMode.电流: type = 0x00; break;
                case DianZiFuZaiEnum.FuZaiMode.功率: type = 0x02; break;
                case DianZiFuZaiEnum.FuZaiMode.电阻: type = 0x03; break;
                default:
                    break;
            }
            byte[] order = new byte[4] { 0xAA, Addr, modeByte, type };
            return order;
        }
        byte[] CmdReadCurrentValue()
        {
            byte[] order = new byte[25] { 0xAA, Addr, 0x5F,0x00,0x00,0x00,0x00,
               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00 , 0x00 };
            return ByteHelper.GetSumCcBytes(order);
        }
        byte[] CmdReadCurrentValueOk => new byte[3] { 0xAA, Addr, 0x5F };
    }
}
